package bgai.gui;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;


import bgai.gamelogic.Backgammon;
import bgai.gamelogic.CheckerColor;
import bgai.gamelogic.Point;
import bgai.gamelogic.PointException;

public class PointLabel extends JLayeredPane{


	private static final long serialVersionUID = -7534979293878492746L;
	
	
	/**
	 * L'istanza point associata
	 */
	private Point point;
	
	/**
	 * I checker presenti sul point
	 */
	private ArrayList<Checker> checkersOnPoint;
	
	/**
	 *  I pannelli sovrapposti che contengono le pedine situate sulla stessa punta
	 */	
	private JPanel bottomPanel,halfPanel,upperPanel;
	
	/**
	 * Il pannello con l'immagine di background
	 */
	private BgPanel bgPanel;
	
	/**
	 * L'istanza BackgammnGUI su cui si trova questa punta
	 */
	private BackgammonGUI bgGUI;
	
	/**
	 * Istanzia l'oggetto grafico che rappresenta un point
	 * @param color il colore del point
	 * @param Point l'istanza di point associata
	 */
	public PointLabel(CheckerColor color,Point point, BackgammonGUI bgGUI) {
		super();
		this.point=point;
		this.bgGUI=bgGUI;
		
    	//il pannello con l'immagine di background del point
    	bgPanel = new BgPanel(color);  	
    	
    	float percWidth= ((float) ((float)35/100)/6) * bgGUI.getWidth();
		float percHeight= ((float) ((float)80/100)/2) * bgGUI.getHeight();
		
		bgPanel.setPreferredSize(new Dimension((int)percWidth, (int)percHeight));
		bgPanel.setSize(new Dimension((int)percWidth, (int)percHeight));
		
		bgPanel.scaleBg((int)percWidth, (int)percHeight);
		
    	this.setPreferredSize(new Dimension((int)percWidth, (int)percHeight));
    	this.setMinimumSize(new Dimension((int)percWidth, (int)percHeight));
    	this.setBackground(new Color(139,69,19));
    	
    	// il pannello che contiene le prime 5 pedine (da 1 a 5)
		bottomPanel = new JPanel();
		bottomPanel.setPreferredSize(new Dimension((int)percWidth, (int)percHeight));
		bottomPanel.setSize(new Dimension((int)percWidth, (int)percHeight));
		bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.PAGE_AXIS));
		bottomPanel.setOpaque(false);
		bottomPanel.addMouseListener(bgGUI);
		
		//il pannello che contiene le pedine da 6 a 10
		halfPanel = new JPanel();
		halfPanel.setPreferredSize(new Dimension((int)percWidth, (int)percHeight));
		halfPanel.setSize(new Dimension((int)percWidth, (int)percHeight));
		halfPanel.setLayout(new BoxLayout(halfPanel, BoxLayout.PAGE_AXIS));
		halfPanel.setOpaque(false);
		halfPanel.addMouseListener(bgGUI);
		
		//il pannello che contiene le pedine da 11 a 15
		upperPanel = new JPanel();
		upperPanel.setPreferredSize(new Dimension((int)percWidth, (int)percHeight));
		upperPanel.setSize(new Dimension((int)percWidth, (int)percHeight));
		upperPanel.setLayout(new BoxLayout(upperPanel, BoxLayout.PAGE_AXIS));
		upperPanel.setOpaque(false);
		upperPanel.addMouseListener(bgGUI);
		
		this.add(bgPanel,new Integer(1));
		this.add(bottomPanel,new Integer(2));
		
		/*Lascia commentate queste 2 righe perche' Cursor.HAND_CURSOR quando le pedine sono un layer sotto non funzionano */
		//this.add(halfPanel, new Integer(3));
		//this.add(upperPanel, new Integer(4));
		
		checkersOnPoint= new ArrayList<Checker>();
	}
	
	
	/**
	 * Restituisce l'istanza Point asssociata
	 * @return vedi descrizione metodo
	 */
	public Point getPoint(){
		
		return this.point;
		
	}
	
	
	/**
	 * Restituisce il colore delle pedine presenti su questo checker
	 * @return vedi descrizione metodo
	 */
	public CheckerColor getCheckerColor(){
	
		if(checkersOnPoint.size()==0) return null;
		else return checkersOnPoint.get(checkersOnPoint.size()-1).getColor();
		
	}
	
	
	/**
	 * Ottiene il numero di checkers presenti graficamente sul point
	 * @return vedi descrizione metodo
	 */
	public int getNumCheckers(){
	
			return checkersOnPoint.size();
		
	}
	
	
	/**
	 * Rimuovi il placeHolder dal point
	 */
	public void hidePlaceholder(){
		
		
		if(checkersOnPoint.size()==0) return; //non e' presente alcuna pedina
		
		//l'ultimo cheker inserito deve essere un placeholder
		Checker c= checkersOnPoint.get(checkersOnPoint.size()-1);
		if(c.isPlaceHolder()){
			c.setCursor(null);
			c.removeMouseListener(bgGUI);
			removeChecker();
		}
		
	}
	
	
	
    /**
	 * Aggiunge un checker o un placeholder sul point
	 * @param col il checker da aggiungere (questo parametro non ha importanza se parametro placeholder==true)
	 * @param placeholder true se va aggiunto un placeholder, false altrimenti
	 */
	public void insertChecker(CheckerColor col, boolean placeholder){
			
		
		if(checkersOnPoint.size()!=0 && checkersOnPoint.get(checkersOnPoint.size()-1).isPlaceHolder()){  //Non dovrebbe accadere, dovrebbe gia' essere stato chiamato hidePlaceHolder
			
			throw new PointException(point, "Si sta inserendo un checker in un point in cui e' ancora visualizzato il placeholder");
			
		}
		
		if(checkersOnPoint.size()!=0 && !placeholder){
			
			if(col!=checkersOnPoint.get(checkersOnPoint.size()-1).getColor()){
				
				throw new PointException(point, "Non si possono mantenere checker di colori diversi sullo stesso point");
				
			}
			
		}
			
				
		// creo il nuovo checker del colore passato
		Checker c= new Checker(col,point.getPosition());
		
		ImageIcon img=null;
		
		//int numCheckers = this.getPoint().getNum();
		int numCheckers =checkersOnPoint.size()+1;
		
		if(placeholder){ //devo aggiungere un placeholder
			
			img= c.setPlaceholderImage((int)(-1),(int)(bgPanel.getBgHeight()/6));
			Cursor handCurs = new Cursor(Cursor.HAND_CURSOR);
			c.setCursor(handCurs);
			c.addMouseListener(bgGUI);
		}
		
		else{
			
			// imposto l'immagine di default del checker scalata come specificato
			img= c.setScaledImage((int)(-1),(int)(bgPanel.getBgHeight()/6));
			
		}
		
		/*System.out.println("INSERT");
		System.out.println("point "+point.getPosition()+", numCheckers: "+numCheckers);
		if(checkersOnPoint!=null);
			System.out.println("CheckersOnPoint: "+checkersOnPoint.size());
		System.out.println();*/
		
		JPanel panel=null;
		int i = -1;
		
		if(numCheckers<=5){ // se ==5 significa che ero a 4 checker devo mettere il quinto
			
			panel=bottomPanel;
			i=5;

		}
		
		else if(numCheckers<=10){ // point che contiene da 6 checker a 10 checker
			
			if(numCheckers==6){ // e' il primo checker che devo mettere sovrapposto nel pannello in mezzo
				this.add(halfPanel, new Integer(3));
				this.revalidate();
				this.repaint();
			}
			
			if(numCheckers==6 && point.getPosition()>12){ // e' il primo checker da sovrapporre ai primi 5 ed il point fa parte di quelli nella parte alta delle tavole
				halfPanel.add(Box.createRigidArea(new Dimension(img.getIconWidth(),img.getIconHeight()/2)));
			}
			
			panel=halfPanel;
			i=10;
			
		}
		
		else if(numCheckers<=15){ // point che contiene da 11 a 15 checker
	
			if(numCheckers==11){ // e' il primo checker che devo mettere sovrapposto nel pannello superiore
				this.add(upperPanel, new Integer(4));
				this.revalidate();
				this.repaint();
			}			
			panel=upperPanel;
			i=15;
		}
		
		else{ //non ci possono essere piu' di 15 checker nel point
			
			throw new PointException(point, "Il numero delle pedine nel point non puo' essere > 15");
			
		}
		
		// salvo la nuova JLabel inserita (che puo' essere checker o placeholder)
		checkersOnPoint.add(c);
		
		if(point.getPosition()<=12){ // se e' un point della parte basse delle tavole
			
			panel.removeAll();
			
			// posizionare le pedine nella parte bassa dei points numerati da 1 a 12
			for(;i>=(checkersOnPoint.size());i--){
				
				if(panel==halfPanel && i==10){ //panel==halfPanel
					
					panel.add(Box.createRigidArea(new Dimension(img.getIconWidth(),img.getIconHeight()/2)));
					
				}
				else{
					
					panel.add(Box.createRigidArea(new Dimension(img.getIconWidth(),img.getIconHeight())));
				}
			}
				
			int k=-1;
			if(panel==bottomPanel){
				
				k=0;
				
			}
			else if(panel==halfPanel){
				
				k=5;
			}
			else{ //upperPanel
				
				k=10;
			}
			for(int j=(checkersOnPoint.size()-1);j>=k;j--){
				panel.add(checkersOnPoint.get(j));
			}
			
		}
		else{ //e' un point nella parte alta delle tavole
			// aggiungo graficamente il checker al point
			panel.add(c);
		}

		panel.revalidate();
		panel.repaint();
				
	}
	
	
	/**
	 *Evidenzia l'ultimo checker inserito nel point
	 */
	public void highlightChecker(){
		
		Checker lastInserted= checkersOnPoint.get(checkersOnPoint.size()-1);
		
		if(!lastInserted.isHighlighted()){
			
			// cambio l'immagine della label in quella evidenziata
			lastInserted.setHighlightedImage((int)(-1),(int)(bgPanel.getBgHeight()/6));
		
			Cursor handCurs = new Cursor(Cursor.HAND_CURSOR);
			lastInserted.setCursor(handCurs);
				
			// aggiungo il listener per il click sul checker
			lastInserted.addMouseListener(bgGUI);
		}
		
	}
	
	
	/**
	 * Rimuove evidenziazione dall'ultimo checker inserito nel point
	 */
	public void disableHighlightChecker(){
		
		if(checkersOnPoint.isEmpty()) return;
		
		Checker lastInserted= checkersOnPoint.get(checkersOnPoint.size()-1);

		if(lastInserted.isHighlighted()){
			
			lastInserted.setScaledImage((int)(-1),(int)(bgPanel.getBgHeight()/6));
			lastInserted.setCursor(null);
			lastInserted.removeMouseListener(bgGUI);
			
		}

	}
   
	
	/**
	 * Rimuove un checker posizionato sul point (rimuove sempre l'ultimo inserito)
	 */
	public void removeChecker(){
		
			
		int numCheckers = checkersOnPoint.size();
		
		
		JPanel panel=null;

		int i = -1;
		
		if(numCheckers<=5){ // devo rimuovere un checker dal bottomPanel
			
				panel=bottomPanel;
				i=5;
		}
		
		else if(numCheckers<=10){ //devo rimuovere un checker dall'halfPanel
			
			i=10;
	
			panel=halfPanel;				

		}
		
		else if(numCheckers<=15){ //devo rimuovere un checker dall'upperPanel
			
			panel=upperPanel;
			
			i=15;
		}
		
		else{ //non ci possono essere piu' di 15 checker nel point
			
			throw new PointException(point, "Il numero delle pedine nel point non puo' essere > 15");
			
		}
				
		
		/*System.out.println("REMOVE");
		System.out.println("point "+point.getPosition()+", numCheckers: "+numCheckers);
		if(checkersOnPoint!=null);
			System.out.println("CheckersOnPoint: "+checkersOnPoint.size());
		System.out.println();*/
			
		
		if(point.getPosition()<=12){ // la punta e' nella parte inferiore delle tavole
			
			checkersOnPoint.remove(checkersOnPoint.size() - 1);
			
			panel.removeAll();
			
			ImageIcon img=(new Checker(CheckerColor.WHITE)).setScaledImage((int)(-1),(int)(bgPanel.getBgHeight()/6)); //checker usato solo per ottenere larghezza ed altezza img

			
			// posizionare le pedine nella parte bassa dei points numerati da 1 a 12
			for(;i>=(checkersOnPoint.size());i--){
				
				if(panel==halfPanel && i==10){ //panel==halfPanel
					
					panel.add(Box.createRigidArea(new Dimension(img.getIconWidth(),img.getIconHeight()/2)));
				}
				else{
					panel.add(Box.createRigidArea(new Dimension(img.getIconWidth(),img.getIconHeight())));
				}
			}
			
			int k=-1;
			if(panel==bottomPanel){
				
				k=0;
				
			}
			else if(panel==halfPanel){
				
				k=5;
			}
			else{ //upperPanel
				
				k=10;
			}
			
			for(int j=(checkersOnPoint.size()-1);j>=k;j--){
				panel.add(checkersOnPoint.get(j));
			}
			
			panel.revalidate();
			panel.repaint();
			
		}
		else{ //la punta e' nella parte superiore delle tavole
			
			//rimuovo l'ultimo checker inserito dal pannello...
			panel.remove(checkersOnPoint.get(checkersOnPoint.size() - 1));
			//...e dall'array di checker
			checkersOnPoint.remove(checkersOnPoint.size() - 1);
			panel.revalidate();
			panel.repaint();
		}
		
		if(numCheckers==6 || numCheckers==11){ //ho rimosso l'unico checker presente in halfPanel o in upperPanel (devo rimuovere halfPanel o upperPanel)
			// rimuovo tutti gli eventuali spazi aggiunti ad halfPanel
			panel.removeAll();
			panel.revalidate();
			panel.repaint();
			this.remove(panel);
			this.revalidate();
			this.repaint();
		}
				
	}
    
	
	
	/**
	 * Pannello con l'immagine di sfondo del point
	 */
	class BgPanel extends JPanel{
		

		private static final long serialVersionUID = -4930163403943479099L;
		
		/**
		 * Il colore del point. Necessario per caricare l'immagine corretta.
		 */
		private CheckerColor color;
		
		/**
		 * L'immagine di sfondo del point
		 */
		private ImageIcon bgImg=null;
		
		
		public BgPanel(CheckerColor color){
			super();
			this.color = color;
		}
		
		
		/**
	     * Restituisce l'altezza dell'immagine di background
	     * @return vedi descrizione
	     */
	    public int getBgHeight(){
	    	
	    	return bgImg.getIconHeight();
	    }
	    
	    
	    /**
	     * Restituisce la larghezza dell'immagine di background
	     * @return vedi descrizione
	     */
	    public int getBgWidth(){
	    	return bgImg.getIconWidth();
	    }
	    
	    
	    /**
	     * Restituisce l'immagine di sfondo del point o null se l'immagine non e' ancora stata caricata
	     * @return vedi descrizione metodo
	     */
	    public ImageIcon getBgImg(){
	    	
	    	return bgImg;
	    }
		
	    /**  Disegna l'immagine di sfondo del Point*/ 
	    @Override
	    protected void paintComponent(Graphics g)
		{
	    	
	    	super.paintComponent(g);
	    	g.drawImage(bgImg.getImage(), 0, 0,null);
	    	
		}
	    
	    
	    /**
	     * Scala il background
	     * @param width la nuova larghezza
	     * @param height la nuova altezza
	     */
	    private void scaleBg(int width,int height){
	    	
	    	Image tmpImg=null;
	    	
	    	if(this.color==CheckerColor.BLACK){
				//background con punta nera
	    		if(point.getPosition()<=12){
	    			tmpImg= new ImageIcon(PointLabel.class.getResource("/img/blackPoint.jpg")).getImage();
	    		}
	    		else{
	    			tmpImg= new ImageIcon(PointLabel.class.getResource("/img/blackPointReverse.jpg")).getImage();
	    		}
			}
			
			else if(this.color==CheckerColor.WHITE){
				//background con punta bianca
				if(point.getPosition()<=12){
	    			tmpImg= new ImageIcon(PointLabel.class.getResource("/img/whitePoint.jpg")).getImage();
				}
				else{
					tmpImg= new ImageIcon(PointLabel.class.getResource("/img/whitePointReverse.jpg")).getImage();
				}
			}
	    	
		    this.bgImg = new ImageIcon(
	        		tmpImg.getScaledInstance(width, height, Image.SCALE_SMOOTH)
	        		);
		    
	    	this.repaint();
	    }
		
		
		
	}
	

}
